#include <boost/algorithm/string.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <nice2d/components/attributetable.h>
#include <nice2d/spriteattributedecorator.h>
#include <nice2d/piece/piece.h>

IMPLEMENT_OBJECT(SpriteAttributeDecorator, SpriteDecorator)

class SpriteAttributeDecoratorData
{
public:
    sf::Text text;
    std::vector<int32_t> attributes;
    std::string separator = "-";
};

SpriteAttributeDecorator::SpriteAttributeDecorator(const TextOption &option):
    data(new SpriteAttributeDecoratorData)
{
    TextOption::apply(data->text, option);
}

SpriteAttributeDecorator::~SpriteAttributeDecorator()
{
}

void SpriteAttributeDecorator::setAttibutes(const std::vector<int32_t> &attributes,
                                            const std::string &separator)
{
    data->attributes = attributes;
    data->separator = separator;
    update();
}

void SpriteAttributeDecorator::setTextColor(const sf::Color &color)
{
    data->text.setFillColor(color);
}

sf::Color SpriteAttributeDecorator::getTextColor() const
{
    return data->text.getFillColor();
}

void SpriteAttributeDecorator::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
    target.draw(data->text, states);
}

void SpriteAttributeDecorator::update()
{
    auto sprite = getSprite();
    if (sprite.expired())
        return;

    auto holder = sprite.lock();
    auto table = GET_COMPONENT(holder, AttributeTable1D);

    std::vector<std::string> texts;
    auto itr = data->attributes.begin();
    while (itr != data->attributes.end()) {
        auto val = table->get(*itr);
        if (val.has_value())
            texts.push_back(std::to_string(val.value()));
        else
            texts.push_back("N/A");
        itr ++;
    }

    auto text = boost::algorithm::join(texts, data->separator);
    data->text.setString(text);

    auto box = holder->getBoundingBox();

    data->text.setRotation(getRotate());
    auto textBox = data->text.getGlobalBounds();
    auto position = Entity::adjustPosition(box, {textBox.width, textBox.height},getHAligment(),getVAlignment(), 0.0f, 0.0f);
    position.x -= box.left;
    position.y -= box.top;
    position.x -= textBox.left;
    position.y -= textBox.top;
    position += getOffset();
    data->text.setPosition(position);
}

void SpriteAttributeDecorator::updateAnchor()
{
    update();
}

PTree SpriteAttributeDecorator::serialize()
{
    PTree node;
    return node;
}

void SpriteAttributeDecorator::deserialize(const PTree &node)
{

}
